/**
* 版权所有：福建邮科电信业务部厦门研发中心 
*====================================================
* 文件名称: AbstractFileTemplateEngine.java
* 修订记录：
* No    日期				作者(操作:具体内容)
* 1.    2013-4-10			詹保山(创建:创建文件)
*====================================================
* 类描述：(说明未实现或其它不应生成javadoc的内容)
* 
*/
package com.devframe.component.ftlprocess.engine;

import java.io.Writer;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import com.devframe.component.ftlprocess.FTLProcessGlobalConstants;
import com.devframe.component.ftlprocess.MyFTLProcessContextContainer;
import com.devframe.component.ftlprocess.MyFTLProcessHandleBean;
import com.devframe.component.ftlprocess.cache.MyFTLProcessCacheManager;
import com.devframe.component.ftlprocess.engine.impl.MyFTLProcessDefaultEngineImpl;
import com.devframe.component.ftlprocess.meta.DataSet;
import com.devframe.component.ftlprocess.meta.Model;
import com.devframe.component.ftlprocess.meta.Report;
import com.devframe.sysbase.dao.BaseDao;

public abstract class AbstractFTLProcessEngine {
	protected static Logger logger = Logger.getLogger(MyFTLProcessDefaultEngineImpl.class);
	
	private BaseDao baseDao;
	/**
	 * 进行结果的转换，如果是多行的按多行进行返回，如果是单行的直接取结果的第一行
	 * @param ls
	 * @return
	 * @author:詹保山
	 */
	protected Object convertResult(List ls){
		if(ls!=null && ls.size()==1){
			Object obj=ls.get(0);
			if(obj instanceof Map){
				Map map=(Map)obj;
				if(map.size()==1){
					return map.values().iterator().next();
				}else{
					return map;
				}
			}else{
				return obj;
			}
		}
		return ls;
	}
	
	
	/**
	 * Spring Bean 方法的执行：
	 *  如果 方法的参数是1个而且是Map的参数类型，则按这个方法执行：优先执行<br/>
	 *  如果 方法的参数是0 
	 *  
	 * @param bean
	 * @param clientParams
	 * @return
	 * @author:詹保山
	 */
	protected Object execServiceBean(DataSet ds,Map<String,Object> clientParams){
		if(StringUtils.isEmpty(ds.getService())){
			logger.error("没指定Sping 受管的service id");
			return null;
		}
		Object objBean=MyFTLProcessCacheManager.getCacheOfServiceBean(ds.getService());//从自定义的实体BEAN中查找
		if(objBean==null){
			boolean bool=MyFTLProcessContextContainer.getInstance().containsSpringBean(ds.getService());
			if(bool){
				objBean=MyFTLProcessContextContainer.getInstance().getSpringBean(ds.getService());
			}else{
				return null;
			}
		}
		String execMethodName=StringUtils.trim(ds.getMethod());
		Method[] methods=objBean.getClass().getMethods();
		Method execMethod=null;
		//判断是否有参数
		boolean noParams=false;
		for(Method method:methods){
			String methodName=method.getName();
		    if(methodName.equals(execMethodName)){
				Class[] paramsArray=method.getParameterTypes();
				//参数是1个并且是Map结构或参数是0的情况下
				if((paramsArray.length==1 && paramsArray[0].equals(Map.class))||paramsArray.length==0){
					//找到 就退出
					execMethod=method;
					noParams=paramsArray.length==0;
					break;
				}
			}
		}
		//为空的情况下
		if(execMethod==null){
			logger.error("在service【"+ds.getService()+"】实例中没找到method=【"+ds.getMethod()+"】");
			return null;
		}
		//方法的执行
		try {
			if(noParams)
			{
				return execMethod.invoke(objBean);
			}else{
				return execMethod.invoke(objBean, clientParams);
			}
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
				logger.error(e);
			} catch (IllegalAccessException e) {
				e.printStackTrace();
				logger.error(e);
			} catch (InvocationTargetException e) {
				e.printStackTrace();
				logger.error(e);
			}
		return null;
	}
	
	  /**
     * 解析报表头
     * @param handleBean
     * @param report
     * @return
     * @author:詹保山
     */
    protected Map<String,Object> reportNodeProcess(MyFTLProcessHandleBean handleBean,Report report){
    	if(report==null){
    		logger.error("没有创建report实例");
    	}
    	Map<String,Object> root=new HashMap<String, Object>();
		root.put(FTLProcessGlobalConstants.ReportTag, report);
		//解析出report指令的属性
		handleBean.getReportHandle().process(handleBean.getTemplateFile(), root);
		root.remove(FTLProcessGlobalConstants.ReportTag);
		return root;
    }
 
	
	   /**
     * 解析出模版的模型XML
     * @param handleBean
     * @param clientParams
     * @return
     * @author:詹保山
     */
    private Model modelNodeProcess(MyFTLProcessHandleBean handleBean,Map<String,Object> clientParams){
    	String xml=handleBean.getModelHandle().process(handleBean.getTemplateFile(), clientParams);
    	if(logger.isDebugEnabled()){
    		logger.debug("模版文件【="+handleBean.getTemplateFile()+"】，解析获得XML="+xml);
    	}
    	Model model=handleBean.getParserModelXml().parserModelXml(xml);
    	if(logger.isDebugEnabled()){
    		logger.debug("解析出模型实体："+model);
    	}
    	return model;
    }
	
    /**
     * 获取model
     * @param tmplFile
     * @param handleBean
     * @param clientParams
     * @return
     * @author:詹保山
     */
    protected synchronized Model accessModel(String tmplFile,MyFTLProcessHandleBean handleBean, Map<String,Object> clientParams){
    	
    	Model model=MyFTLProcessCacheManager.getCacheOfModel(tmplFile);
    	
    	if(model==null){
    		model=this.modelNodeProcess(handleBean, clientParams);
    		if(logger.isDebugEnabled()){
    			logger.debug("model={"+model+"}");
    		}
    		MyFTLProcessCacheManager.putCacheOfModel(tmplFile, model);
    		//进行解析DataSet中含有的CLASS
    	}
    	return model;
    	
    }
    
    
    /**
     * 获取Report报表上下文的处理 以报表的模板文件名为key,没有,则创建
     * @param tmplFile
     * @return
     * @author:詹保山
     */
    protected synchronized MyFTLProcessHandleBean accessHandleBean(String tmplFile){
    	MyFTLProcessHandleBean handleBean=MyFTLProcessCacheManager.getCacheOfHandleBean(tmplFile);
    	if(handleBean==null){
    		handleBean=new MyFTLProcessHandleBean(MyFTLProcessContextContainer.getInstance().getHandleContext(),tmplFile);
    		handleBean.setTemplateFile(tmplFile);
    		MyFTLProcessCacheManager.putCacheOfHandleBean(tmplFile, handleBean);
    	}
    	return handleBean;
    }
 
    
    
    protected void renderNodeProcess(MyFTLProcessHandleBean handleBean,Map<String,Object> root,Writer writer){
    	handleBean.getRenderHandle().process(writer, handleBean.getTemplateFile(), root);
    }


	public BaseDao getBaseDao() {
		return baseDao;
	}


	public void setBaseDao(BaseDao baseDao) {
		this.baseDao = baseDao;
	}
	
}
